# 1. 函数式编成 example
import math
def add(x, y, f):
    return f(x,.5) + f(y,.5)
print add(25, 9, pow)


# 2. Map 函数 同 js
def format_name(s):
    return s[0].upper() + s[1:].lower()
print list(map(format_name, ['adam', 'LISA', 'barT']))


# 3.reduce 分解求和
# py3 --> from functools import reduce
def prod(x, y):
    return x*y
print reduce(prod, [2, 4, 5, 7, 12])


# 4. filer 同js s.strip()去除空格
# example 过滤出1~100中平方根是整数的数 [1, 4, 9, ...]
import math
def is_sqr(x):
    return math.sqrt(x) % 1 == 0
print filter(is_sqr, range(1, 101))


# 排序 scorted
# 传入两个待比较的元素 x, y，
# 如果 x 应该排在 y 的前面，返回 -1，
# 如果 x 应该排在 y 的后面，返回 1。
# 如果 x 和 y 相等，返回 0。
print sorted(['bob', 'about', 'Zoo', 'Credit'], key = str.lower)


# 柯里化 @example
def calc_prod(lst):
    def prod(x, y):
        return x*y
    def red():
        return reduce(prod, lst)
    return red
f = calc_prod([1, 2, 3, 4])
print f()

# 闭包 example 返回三个函数
def count():
    fs = []
    for i in range(1, 4):
        def s(m = i):
            return m ** 2
        fs.append(s)
    return fs
f1, f2, f3 = count()
print f1(), f2(), f3()


# 匿名函数 关键字 lambda
myabs = lambda x: -x if x < 0 else x
myabs(-1)
# 去重
print filter(lambda s: s and len(s.strip()) > 0, ['test', None, '', 'str', '  ', 'END'])


# decorator 装饰器 --> 不立即执行的函数的回调函数
# 要让 @log 自适应任何参数定义的函数，
# 可以利用Python的 *args 和 **kw，保证任意个数的参数总是能正常调用：
import time
def performance(f):
    def fn(*args, **kw):
        t1 = time.time()
        r = f(*args, **kw)
        t2 = time.time()
        print 'call %s() in %fs' % (f.__name__, (t2 - t1))
        return r
    return fn

@performance
def factorial(n):
    return reduce(lambda x,y: x*y, range(1, n+1))
print factorial(10)
